#include <fstream>
#include <string>
#include "Index.hpp"
#include "Util.hpp"
#include <algorithm>
#include <json/json.h>
#include "Log.hpp"

using namespace LogModule;
namespace ns_searcher
{
    struct InvertedPrint
    {
        uint64_t _id;
        std::vector<std::string> _words; // 存放同一个文档中所有关键字
        int _totalWeight = 0;
    };
    class Searcher
    {
    public:
        Searcher() {}
        ~Searcher() {}

    public:
        void InitSearcher(const std::string &raw_path)
        {
            LOG(LogLevel::INFO) << "开始建立索引";
            // std::cout << "开始建立索引" << std::endl;
            // 1. 获取或者创建index对象
            _index = ns_index::Index::GetInstance();
            // 2. 根据index对象建立索引
            _index->InitIndex(raw_path);
            LOG(LogLevel::INFO) << "建立索引成功";
            // std::cout << "索引建立成功" << std::endl;
        }

        // query: 搜索关键字
        // json_string: 返回给用户浏览器的搜索结果
        void Search(const std::string &query, std::string *json_string)
        {
            LOG(LogLevel::INFO) << "用户搜索:" << query;
            // 1.[分词]:对我们的query进行按照searcher的要求进行分词
            std::vector<std::string> words;
            ns_util::JieBaUtil::CutForSerach(query, &words);
            // for debug
            std::cout << "query进行分词后的结果:" << std::endl;
            for (std::string &word : words)
            {
                std::cout << word << std::endl;
            }
            // 2.[触发]:就是根据分词的各个"词"，进行index查找
            // ns_index::Index::InvertedList invertedListAll;
            std::unordered_map<uint64_t, InvertedPrint> umap;
            for (std::string word : words)
            {
                boost::algorithm::to_lower(word);
                ns_index::Index::InvertedList *invertedList = _index->GetInvertedList(word);
                if (invertedList == nullptr)
                    continue;
                // 特别注意：如果不去重，json串会包含重复的文档
                // invertedListAll.insert(invertedListAll.end(), invertedList->begin(), invertedList->end());
                for (const ns_index::InvertedElem &e : *invertedList)
                {
                    umap[e._id]._id = e._id;
                    umap[e._id]._words.push_back(e._word);
                    umap[e._id]._totalWeight += e._weight;
                }
            }
            std::vector<InvertedPrint> invertedPrint_list;
            for (auto &e : umap)
            {
                invertedPrint_list.emplace_back(e.second);
            }
            // 3.[合并排序]：汇总查找结果，按照相关性(weight)降序排序
            std::sort(invertedPrint_list.begin(), invertedPrint_list.end(),
                      [](const InvertedPrint &e1, const InvertedPrint &e2)
                      { return e1._totalWeight > e2._totalWeight; });
            // 4.[构建]:根据查找出来的结果，构建json串 -- jsoncpp
            Json::Value root;
            for (InvertedPrint &e : invertedPrint_list)
            {
                ns_index::DocInfo *doc = _index->GetForwardIndex(e._id);
                if (doc == nullptr)
                    continue;
                Json::Value item;
                item["title"] = doc->_title;
                // item["desc"] = doc->_content; // 暂时，实际只要摘要
                item["desc"] = GetDesc(e._words[0], doc->_content);
                item["url"] = doc->_url;
                item["weight"] = e._totalWeight;
                item["id"] = e._id;
                root.append(item);
            }
            Json::StyledWriter writer;
            *json_string = writer.write(root);
        }

    private:
        std::string GetDesc(const std::string &word, const std::string &content)
        {
            // 提取前50个字节和后100个字节
            // size_t pos = content.find(word);
            // if (pos == std::string::npos)
            //     return "None1";
            auto iter = std::search(content.begin(), content.end(), word.begin(), word.end(),
                                    [](char e1, char e2) -> bool
                                    {
                                        return std::tolower(e1) == std::tolower(e2);
                                    });
            if (iter == content.end())
                return "None1";
            size_t pos = iter - content.begin();
            size_t beforeStep = 50;
            size_t afterStep = 100;
            size_t begin = 0;
            size_t end = content.size() - 1;
            // begin pos-beforeStep pos  够50个字节，截取50个
            // if (pos - beforeStep > begin)
            if (pos > begin + beforeStep)
                begin = pos - beforeStep;
            // pos pos+afterStep end 够100个字节，截取100个
            if (pos + afterStep < end)
                end = pos + afterStep;
            if (begin >= end)
                return "None2";
            std::string desc = content.substr(begin, end - begin + 1) + "...";
            return desc;
        }

    private:
        ns_index::Index *_index; // 供系统进行查找的索引
    };
}